<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <link href='https://struts.apache.org/highlighter/style/shCoreStruts.css' rel='stylesheet' type='text/css' />
    <link href='https://struts.apache.org/highlighter/style/shThemeStruts.css' rel='stylesheet' type='text/css' />
    <script src='https://struts.apache.org/highlighter/js/shCore.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushPlain.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushXml.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJava.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJScript.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushGroovy.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushBash.js' type='text/javascript'></script>
    <script type="text/javascript">
        SyntaxHighlighter.defaults['toolbar'] = false;
        SyntaxHighlighter.all();
    </script>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>FreeMarker Tags</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="guides.html">Guides</a>&nbsp;&gt;&nbsp;<a href="tag-developers-guide.html">Tag Developers Guide</a>&nbsp;&gt;&nbsp;<a href="freemarker-tags.html">FreeMarker Tags</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">FreeMarker Tags</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14294">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14294">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14294">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14294">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14294">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14294">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><p>FreeMarker tags are extensions of the generic <a shape="rect" href="struts-tags.html">Struts Tags</a> provided by the framework. You can jump right in just by knowing the generic structure in which the tags can be accessed: <code>&lt;@s.tag&gt; ...&lt;/@s.tag&gt;</code>, where <em>tag</em> is any of the <a shape="rect" href="struts-tags.html">tags</a> supported by the framework.</p>

<p>For example, in JSP you might create a form using Struts tags.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>JSP Form</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;s:form action="updatePerson"&gt;
    &lt;s:textfield label="First name" name="firstName"/&gt;
    &lt;s:submit value="Update"/&gt;
&lt;/s:form&gt;
</pre>
</div></div>

<p>In FreeMarker the same form can also be built using Struts tags.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>FTL Form</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;@s.form action="updatePerson"&gt;
    &lt;@s.textfield label="First name" name="firstName"/&gt;
    &lt;@s.submit value="Update"/&gt;
&lt;/@s.form&gt;
</pre>
</div></div>
<p><em>But, wait there's more!</em></p>

<p>Aside from doing everything that the JSP tags do, the FTL tags boast additional features that you can use to make your pages even easier to code. You can even invoke third-party JSP taglibs as if there were native FTL tags.</p>

<h2 id="FreeMarkerTags-AttributesandParameters">Attributes and Parameters</h2>

<p>Unlike older versions of JSP (in which the <a shape="rect" href="jsp-tags.html">JSP Tags</a> are based), FreeMarker allows for <em>dynamic attributes</em>, much like JSP 2.0. You can supply attributes to the tags that the tag doesn't explicitedly support. Those attributes that cannot be applied directly to the tag object will be set to the tag's general-purpose <code>parameters</code> Map.</p>

<p>Suppose we wanted to build an URL in a JSP. The URL needs to take an arbitary parameter to the query string, that (being arbitary) isn't specified on the URL tag. In a JSP, we'd have to use the <code>url</code> and <code>param</code> tags together.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Creating a URL with a query string (JSP)</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;s:url value="somePage"&gt;
    &lt;s:param name="personId" value="%{personId}"/&gt;
&lt;/s:url&gt;
</pre>
</div></div>

<p>In FreeMarker, we can pass the arbitrary parameter directly and create the URL in one simple statement.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Creating a URL with a query string (FTL)</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;@s.url value="somePage" personId="${personId}"/&gt;
</pre>
</div></div>

<h3 id="FreeMarkerTags-Usinginlineattributeswithtemplates">Using inline attributes with templates</h3>

<p>Suppose you created a "three column" theme to replace the typical two column theme (xhtml). You might want an additional parameter to display in the third column called "description". Using FreeMarker, you can just pop the description attribute into the textfield tag, no fuss, no muss.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Passing an attribute to the template</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;@s.form action="updatePerson"&gt;
    &lt;@s.textfield label="First name" name="firstName" description="..."/&gt;
    &lt;@s.submit value="Update"/&gt;
&lt;/@s.form&gt;
</pre>
</div></div>

<p>In the new template, the description is referenced via the parameters Map: "${parameters.description}".</p>

<div class="confluence-information-macro confluence-information-macro-tip"><p class="title">Advanced uses of the param tag</p><span class="aui-icon aui-icon-small aui-iconfont-approve confluence-information-macro-icon"></span><div class="confluence-information-macro-body">
<p>For simple cases, inline attributes are much easier to use than the <code>param} tag. But, the {{param} tag is more flexible than inline attributes for advanced use cases. For example, {{param</code> can take the entire body of the tag and apply that as the <em>value</em> attribute.</p></div></div>

<h2 id="FreeMarkerTags-AttributeTypes">Attribute Types</h2>

<p>Remember that all tag attributes must first be set as Strings - they are then later evaluated (using <a shape="rect" href="ognl.html">OGNL</a>) to a different type, such as List, int, or boolean. This generally works just fine, but it can be limiting when using FreeMarker which provides more advanced ways to apply attributes. Suppose the following example:</p>
<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;@s.select label="Foo label - ${foo}" name="${name}" list="%{{1, 2, 3}}"/&gt;
</pre>
</div></div>
<p>What will happen here is that each attribute will be evaluated to a String as best it can. This may involve calling the <code>toString</code> method on the internal FreeMarker objects. In this case, all objects will end up being exactly what you would expect. Then, when the tag runs, the <code>list</code> attribute will be converted from a String to a List using <a shape="rect" href="ognl.html">OGNL</a>'s advanced collection support.</p>

<p>But suppose you wish to use FreeMarker's list or hash support instead? You can do this:</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;@s.select label="Foo label - ${foo}" name="${name}" list=[1, 2, 3]/&gt;
</pre>
</div></div>

<p>Notice that the list attribute no longer has quotes around it. Now it will come in to the tag as an object that can't easily be converted to a String. Normally, the tag would just call <code>toString</code>, which would return "[1, 2, 3]" and be unable to be converted back to a List by OGNL. Rather than go through all this back and forth, the frameworks's FreeMarker tag support will recognize collections and not pass them through the normal tag attribute. Instead, the framework will set them directly in the <code>parameters</code> Map, ready to be consumed by the template.</p>

<p>In the end, everything tends to do what you would expect, but it can help to understand the difference of when OGNL is being used and when it isn't, and how attribute types get converted.</p>

<h2 id="FreeMarkerTags-JSPTagSupport">JSP Tag Support</h2>

<p>While the framework provides native FreeMarker Tags, you might wish to use other third-party tags that are only available for JSP. Fortunately, FreeMarker has the ability to run JSP tags. To do so, you must include the JspSupportServlet in the application's <code>web.xml</code>, as this allows the FreeMarker integration to get access to the required objects needed to emulate a JSP taglib container.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Adding JspSupportSerlvet to web.xml</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;servlet&gt;
    &lt;servlet-name&gt;JspSupportServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;org.apache.struts2.views.JspSupportServlet&lt;/servlet-class&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
</pre>
</div></div>

<p>Once you've done that, you can simply add something like this in your templates:</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;#assign cewolf=JspTaglibs["/WEB-INF/cewolf.tld"] /&gt;
...
&lt;@cewold.xxx ... /&gt;
</pre>
</div></div>

<h2 id="FreeMarkerTags-Next:">Next: <a shape="rect" href="velocity.html">Velocity</a></h2></div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
